package com.darren.euc.service.impl;

import com.darren.euc.dao.*;
import com.darren.euc.entity.*;
import com.darren.euc.repository.HanWangDoorRepository;
import com.darren.euc.repository.MemberRepository;
import com.darren.euc.service.ClientService;
import com.darren.euc.service.DeptService;
import com.darren.euc.service.MemberService;
import com.darren.euc.util.*;
import com.darren.euc.util.haqi.HaquAPIHandler;
import com.darren.euc.util.haqi.Response.HaquResponse;
import com.darren.euc.util.haqi.request.AddFaceRequest;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by yanglas on 2018/3/11.
 */
@Service
public class MemberServiceImpl implements MemberService {

    private static final Logger log = Logger.getLogger(MemberServiceImpl.class);

    private Map usersessions = new HashMap<String, Manager>();

    @Autowired
    private MemberDao memberDao;
    @Autowired
    private ClientDao clientDao;
    @Autowired
    private SpaceDao spaceDao;
    @Autowired
    private DeptDao deptDao;
    @Autowired
    private MemberTokenDao tokenDao;

    @Autowired
    private MemberRepository memberRepository;
    
    
    @Autowired
    private HanWangDoorRepository hanWangDoorRepository;
    
    @Autowired
    private DeptService deptService;
    @Autowired
    private ClientService clientService;

    @Override
    public PageBean queryForPageUseHQL(JSONObject data, Integer pageSize, int currentPage) {
        //模糊查询参数
        String hql = "from Member where 1 = 1 and (employStatus <4 or employStatus is null)";
        String parameter = data.getString("parameter");
        Integer clientId = 0;
        try{
            clientId = data.getInt("clientId");
        }catch(Exception e){
            e.printStackTrace();
            clientId = 0;
        }
        PageBean thePage = null;
        if(StringUtils.isEmpty(parameter)){
            if(clientId!=null && clientId>0){
                hql += " and clientId = "+clientId+" ";//数字不管注入了
            }
            hql = hql +" order by createTime desc";
            thePage  =  memberDao.queryForPageByHQL(hql,pageSize,currentPage);
        }else{

            hql = "select m.* from euc_member  m  left join  euc_client c on m.client_id = c.id  where   (m.employ_status !=4  or m.employ_status is null) " +
                    " and (c.company_name like ? or m.mobile = ? or m.name like ? or m.nick_name like ?) ";
            if(clientId!=null && clientId>0){
                hql += " and m.client_id = "+clientId+" ";//数字不管注入了
            }
            hql = hql +" order by m.create_time desc ";
            thePage  =  memberDao.queryForPageBySQL(hql,pageSize,currentPage,new Object[]{parameter+"%",parameter,parameter+"%",parameter+"%"});
        }
       // EmployStatusEnum.getDescByKey();
//        hql = hql +" order by createTime desc";
        thePage.setList(processGetInfos(thePage.getList()));
        return thePage;
    }

    /**
     * 获取相关入驻信息描述，空间描述，客户描述
     * @param members
     * @return
     */
    private List processGetInfos(List<Member> members) {
        //得到相应的id们
        if (CollectionUtils.isEmpty(members))
            return members;
        Set<Integer> userIds = new HashSet<>();//公司客户
        Set<Integer> spaceIds = new HashSet<>();//空间列表
        spaceIds = members.stream().map(Member::getSpaceId).collect(Collectors.toSet());
        userIds = members.stream().map(Member::getClientId).collect(Collectors.toSet());
       // spaceIds.removeIf(spaceId -> spaceId == null);
       // userIds.removeIf(userId -> userId == null);
        List<Space> spaceList = null;
        List<Client> clientList = null;
        userIds.remove(null);
        spaceIds.remove(null);
        if (!CollectionUtils.isEmpty(userIds)) {
           // clientList = clientDao.queryByCondition(hql, new ArrayList<>(userIds));
            List<Integer> ids = new ArrayList<>(userIds);
            clientList = clientDao.findByIds(ids);
        }
        if (!CollectionUtils.isEmpty(spaceIds)){
//            spaceList = spaceDao.queryByCondition(hql, new ArrayList<>(spaceIds));
            List<Integer> ids = new ArrayList<>(spaceIds);
            spaceList = spaceDao.findByIds(ids);
            log.info("spaceList :"+spaceList.toString());
        }
        //遍历设置
        for(Member member:members){
            member.setEmployStatusDesc(EmployStatusEnum.getDescByKey(member.getEmployStatus()));
            if(!CollectionUtils.isEmpty(clientList) && member.getClientId() != null){
                Optional<Client> clientOptional = clientList.stream().filter(client -> client.getId().equals(member.getClientId())).findFirst();
                try{

                    member.setCompanyName(clientOptional.get().getCompanyName());
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(!CollectionUtils.isEmpty(spaceList) && member.getSpaceId() != null && member.getSpaceId() > 0 ) {

                Optional<Space> spaceOptional = spaceList.stream().filter(space -> space.getId().equals(member.getSpaceId())).findFirst();
                try{
                    member.setBelongSpaceName(spaceOptional.get().getSpaceName());

                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }


        return members;
    }

    @Override
    public Member findByMemberId(Integer id) {
        return memberDao.findById(id);
    }
    
    
    @Override
    public Member findByIcCard(String icCard){
    	return memberDao.findByIcCard(icCard);
    }

    @Override
    public Member saveMember(Member member) throws Exception{
        ThreadLocalUtil.remove();
        try {
            if(member.getId()== null){
                return add(member);
            }
            return edit(member);
        }catch (Exception e){
            e.printStackTrace();
            String msg = ThreadLocalUtil.get("msg");
            ThreadLocalUtil.remove();
            throw new Exception(msg);
        }
    }

    @Transactional
    public Member edit(Member member) throws Exception {
        Member dbMember = memberDao.findById(member.getId());
        if(dbMember != null
        		&& dbMember.getWristBandsNumber() != null
        		&& !"".equals(dbMember.getWristBandsNumber().trim())
        		&& dbMember.getRoomAccess() != null 
        		&& !"".equals(dbMember.getRoomAccess().trim())){
        	List<Integer> oldRoomIds = new ArrayList<Integer>();
        	String[] dbRoomIds = dbMember.getRoomAccess().split(",");
        	if(member.getRoomAccess() != null && !"".equals(member.getRoomAccess().trim())){
        		String[] newRoomIds = member.getRoomAccess().split(",");
        		for(String dbRoomId:dbRoomIds){
        			boolean isOld = true;
        			for(String newRoomId:newRoomIds){
        				if(newRoomId.equals(dbRoomId)){
        					isOld = false;
        					break;
        				}
        			}
        			if(isOld == true){
        				oldRoomIds.add(Integer.valueOf(dbRoomId));
        			}
        		}
        	}else{
        		for(String dbRoomId:dbRoomIds){
        			oldRoomIds.add(Integer.valueOf(dbRoomId));
        		}
        	}
        	if(oldRoomIds.size() > 0){
        		List<HanWangDoor> hanWangDoors = hanWangDoorRepository.findMemberDeletedHanWangRooms(oldRoomIds);
        		for(HanWangDoor hanWangDoor:hanWangDoors){
        			try{
        				HanWangUtil.deleteEmployeeInfo(hanWangDoor.getIp(), hanWangDoor.getPort(), hanWangDoor.getPassword(), Integer.valueOf(dbMember.getWristBandsNumber()));
        			}catch(Exception ex){
        				log.info(ex.getMessage(),ex);
        			}
        		}
        	}
        }
        
        boolean needPush ;
        if(dbMember != null){
            needPush = this.judgeNeedPush(member,dbMember);
            MyBeanUtils.copyPropertiesIgnoreNull(member,dbMember);
            dbMember.setLastModifyTime(new Date());
            memberDao.save(dbMember);
            memberDao.updateMemberStatus();
            dbMember = memberDao.findById(dbMember.getId());
            if(needPush){
                String msg = this.pushToHaqiFaceRecognition(dbMember);
                if(msg != null){
                    ThreadLocalUtil.set("msg",msg);
                    throw new Exception(msg);
                }
            }
            return dbMember;
        }
        return null;
    }

    private boolean judgeNeedPush(Member member, Member dbMember) {
        //1.原先没有而后有的
        if(StringUtil.isEmpty(dbMember.getFaceUrl()) && !StringUtils.isEmpty(member.getFaceUrl())){
            return true;
        }
        //2.原先有而后没有的。。。过
        if(!StringUtil.isEmpty(dbMember.getFaceUrl()) && StringUtils.isEmpty(member.getFaceUrl())){
            return false;//有了的数据不会清空，只允许改
        }
        //3.2者不同
        if(!StringUtil.isEmpty(dbMember.getFaceUrl()) && !StringUtil.isEmpty(member.getFaceUrl())){
            if(!dbMember.getFaceUrl().equals(member.getFaceUrl())){
                return true;
            }
        }
        //变为离场或者删除时，需要推送
        if((dbMember.getEmployStatus()==1 && member.getEmployStatus()!=1) ||
           (dbMember.getEmployStatus()!=1 && member.getEmployStatus()==1)){
            return true;
        }
        return false;
    }

    @Transactional
    public Member add(Member member) throws Exception {
        //查询db是否存在
        if(StringUtil.isEmpty(member.getMobile())){
            throw new Exception("手机号不可以为空");
        }
        Member dbMember = memberDao.findByMobile(member.getMobile());
        if(dbMember != null){//已经注册
            member.setCreateTime(new Date());
           // member.setPassword(EncryptAESUtil.getEncryption(Constant.DEFAULT_PASSWORD, PropertyHelper.getEncryptKey()));
            if(StringUtil.isEmpty(dbMember.getPassword())){
                member.setPassword(EncryptAESUtil.getEncryption(Constant.DEFAULT_PASSWORD, PropertyHelper.getEncryptKey()));
            }else{
                member.setPassword(dbMember.getPassword());
            }
            if(member.getClientId() != null && !member.getClientId().equals(dbMember.getClientId())){
                //公司有变动,判断人数
                String infos = this.judgeFull(member.getClientId());
                if(infos != null){
                    ThreadLocalUtil.set("msg",infos);
                    throw new Exception(infos);
                }
            }
            //只要编辑，就默认驻场
            member.setEmployStatus(1);
            MyBeanUtils.copyPropertiesIgnoreNull(member,dbMember);
            if(!StringUtils.isEmpty(member.getFaceUrl())){
                String msg = this.pushToHaqiFaceRecognition(member);
                if(msg != null){
                    ThreadLocalUtil.set("msg",msg);
                    throw new Exception(msg);
                }
            }
            //  dbMember.setEmployStatus(1);
            memberDao.update(dbMember);
            memberDao.updateMemberStatus();
            dbMember = memberDao.findById(dbMember.getId());
            return dbMember;
        }else{
            String infos = this.judgeFull(member.getClientId());
            if(infos != null){
                ThreadLocalUtil.set("msg",infos);
                throw new Exception(infos);
            }
            member.setCreateTime(new Date());
            if(StringUtil.isEmpty(member.getPassword())){//新增时如果没有密码才设置为默认密码
                member.setPassword(EncryptAESUtil.getEncryption(Constant.DEFAULT_PASSWORD, PropertyHelper.getEncryptKey()));
            }else{
                member.setPassword(member.getPassword());
            }
          //  member.setPassword(EncryptAESUtil.getEncryption(Constant.DEFAULT_PASSWORD, PropertyHelper.getEncryptKey()));
            //设置会员状态
            member.setEmployStatus(1);
            memberDao.save(member);
            memberDao.updateMemberStatus();
            member = memberDao.findById(member.getId());
            //先保存后得到了id，在执行推送
            if(!StringUtils.isEmpty(member.getFaceUrl())){
                String msg = this.pushToHaqiFaceRecognition(member);
                if(msg != null){
                    ThreadLocalUtil.set("msg",msg);
                    throw new Exception(msg);
                }
            }
            return member;
        }
    }

    private String judgeFull(Integer clientId) {
        if(clientId == null || clientId<1)
            return null;
        List<Integer> status = new ArrayList<>();
        status.add(1);
        status.add(2);
        Integer alreadyIn = memberRepository.findByClientIdAndEmployStatusIn(clientId,status);
        if(alreadyIn<1){
            return null;
        }
        return clientService.judgeFull(alreadyIn,clientId);
    }

    private String pushToHaqiFaceRecognition(Member member) {
        AddFaceRequest addFaceRequest = new AddFaceRequest();
        addFaceRequest.setUserCode(IdToCodeHelper.idToCodeWithoutPrefix(member.getId()));
        addFaceRequest.setAppCode(PropertyConfigurer.getPropertiesStr("haqi.appcode"));
        addFaceRequest.setAddress(member.getBelongSpaceName());
        addFaceRequest.setEmail(member.getEmail());
       // addFaceRequest.setImgFile(member.getFaceUrl());//头像地址
        addFaceRequest.setImgUrl(member.getFaceUrl());//头像地址
        addFaceRequest.setName(member.getName());
        addFaceRequest.setPhone(member.getMobile());
        //在场，且在合同期间
        Integer counts = memberRepository.findAvailableContractCount(member.getId());
        log.info("[member]counts:"+counts +" status:"+member.getEmployStatus()+" id:"+member.getId());
        if(member.getEmployStatus() ==1  && counts >0){
            log.info("[member] employ_status:"+member.getEmployStatus());
            addFaceRequest.setSignalChannelCode(PropertyConfigurer.getPropertiesStr("haqi.signalChannelCode"));//信号道路
        }else{
            //离场和删除的不传信号，打卡失效
            log.info("[member] employ_status:"+member.getEmployStatus());
            addFaceRequest.setSignalChannelCode("");//信号道路
            addFaceRequest.setRemark("用户"+member.getMobile()+"已经删除或者离场");
        }

        addFaceRequest.setLevel(String.valueOf(member.getIsAdmin()));
        String responseStr ;
        if(StringUtils.isEmpty(addFaceRequest.getSignalChannelCode()) && member.getFaceUserId()!=null && member.getFaceUserId()>0){
            //只是更新状态，图片去掉
           // addFaceRequest.setImgUrl("");
            log.info("[member] empty getSignalChannelCode:"+ addFaceRequest.getSignalChannelCode());
            addFaceRequest.setId(member.getFaceUserId());
            responseStr = HaquAPIHandler.updateFace(addFaceRequest);
        }else if(member.getFaceUserId()!=null && member.getFaceUserId()>0){
            //更新头像
            addFaceRequest.setId(member.getFaceUserId());
            log.info("[member]   getFaceUserId:"+ member.getFaceUserId());
            responseStr = HaquAPIHandler.updateFace(addFaceRequest);
        }else{
            log.info("infos:"+addFaceRequest.toString());
            if(StringUtil.isEmpty(addFaceRequest.getImgUrl())){
                log.info("infos: imgUrl is null");
                return null;
            }
            responseStr = HaquAPIHandler.addFace(addFaceRequest);
        }
        //String responseStr = HaquAPIHandler.addFace(addFaceRequest);
         JSONObject jsonObject =JSONObject.fromObject(responseStr);
         String message ;
         try{
             message = jsonObject.getString("message");
         }catch(Exception e){
            e.printStackTrace();
             message="";
         }
        HaquResponse haquResponse = new HaquResponse(jsonObject.getInt("code"),message,jsonObject.get("data"));
        if(!haquResponse.getCode().equals(2000)){
            return haquResponse.getMessage();
        }
        // 上传成功以后
        JSONObject data = jsonObject.getJSONObject("data");
        Long faceUserId = data.getLong("id");
        member.setFaceUserId(faceUserId);
        memberDao.merge(member);
        return null;
    }


    @Override
    public Member login(String mobile, String password) throws Exception {
        Member member = memberDao.findByMobile(mobile);
        if(member != null && member.getEmployStatus()>3){
            throw new Exception("用户已被删除");
        }
        //todo:校验密码有效性
        if (member == null)
            throw new Exception("该手机号未注册");

        if (password == null)
            throw new Exception("密码为空");

        String _password = EncryptAESUtil.getEncryption(password, PropertyHelper.getEncryptKey());
        if (!_password.equals(member.getPassword()))
            throw new Exception("密码错误");

        //member.setPassword("");//避免返回密码数据

        if (member.getClientId() != null){
            Client client = clientDao.findById(member.getClientId());
            if (client != null){
                member.setCompanyName(client.getCompanyName());
            }
        }
        return member;
    }

    @Override
    public void register(String mobile, String password) throws Exception {

        Member member = memberDao.findByMobile(mobile);
        if (member != null && member.getEmployStatus()<4){
            throw new Exception("注册失败，手机号码被占用");
        }
//        if(member != null){
//            //删除再注册
//            member.setClientId(null);
//            member.setSpaceId(null);
//            member.setFaceUrl(null);
//            member.setFaceUserId(null);
//            this.saveMember(member);
//            return;
//        }
        //设置注册用户初始数据
        member = new Member();
        member.setMobile(mobile);
        member.setPassword(EncryptAESUtil.getEncryption(password, PropertyHelper.getEncryptKey()));
        member.setCreateTime(new Date());
        member.setSpaceId(0);
        member.setEmployStatus(2);//未入住
        this.saveMember(member);
    }

    @Override
    public String updateToken(Member member) {
        //使用用户信息创建一个token值，生成方式随意保证最基本的不重复就可以

        String token = "T_" + Objects.hash(member.getMobile(), System.currentTimeMillis());
        //token放入缓存
        usersessions.put(token, member);
        MemberToken memberToken = tokenDao.findById(member.getId());
        if (memberToken == null){
            memberToken = new MemberToken();
            memberToken.setMemberId(member.getId());
            memberToken.setToken(token);
            memberToken.setUpdateTime(new Date());
            tokenDao.save(memberToken);
        }else {
            memberToken.setToken(token);
            memberToken.setUpdateTime(new Date());
            tokenDao.update(memberToken);
        }

        return token;
    }

    @Override
    public Member findByToken(String token) {
        Object obj = usersessions.get(token);
        if (obj == null)
            obj = memberDao.findByToken(token);

        return obj == null ? null : (Member) obj;
    }

    @Override
    public void logout(String token) {
        usersessions.remove(token);
        String sql = "SELECT * FROM euc_member_token WHERE token='"+token+"'";
        PageBean<MemberToken> pageBean = tokenDao.queryForPageBySQL(sql, 1, 1);

        if (pageBean.getList().size() > 0){
            MemberToken memberToken = pageBean.getList().get(0);

            memberToken.setToken("");
            memberToken.setUpdateTime(new Date());
            tokenDao.save(memberToken);
        }
    }

    @Override
    public void repass(String mobile, String password) {
        Member member = memberDao.findByMobile(mobile);
        member.setPassword(EncryptAESUtil.getEncryption(password, PropertyHelper.getEncryptKey()));
        memberDao.update(member);
    }

    @Override
    public List findDeptByClientid(Integer clientId) {
        String sql = "select `dept_id`,`dept_name`,`pid` from euc_dept WHERE client_id=?";

        return deptDao.getDataMapList(sql, clientId);
    }

    @Override
    public List findMemberList(Kv kv) {

        String sql = "SELECT `id` member_id,`name` member_name,`email` email, `id_card` idCard, `mobile`,`face_url`,m.`dept_id`, d.`dept_name`" +
                "FROM euc_member m LEFT JOIN euc_dept d ON m.dept_id=d.dept_id WHERE 1=1";
        if (kv.get("client_id") != null)
            sql += " AND m.client_id="+kv.get("client_id");
        if (kv.get("dept_id") != null)
            sql += " AND m.dept_id="+kv.get("dept_id");
        sql += " and m.employ_status < 4 ";
        return memberDao.getDataMapList(sql);
    }

    @Override
    public void memberUpdate(Integer id, String name, String email) {
        Member member = memberDao.findById(id);

        member.setName(name);
        member.setEmail(email);

        memberDao.update(member);
    }

    @Override
    public Map findMemberInfo(int member_id) {
        String sql = "SELECT m.id as member_id,m.client_id,m.nick_name,m.mobile,m.email,m.face_url,m.name as member_name" +
                ",c.company_name as client_name, d.dept_name" +

                " FROM euc_member m" +
                " LEFT JOIN euc_client c ON m.client_id = c.id" +
                " LEFT JOIN euc_dept d ON m.dept_id=d.dept_id" +
                " WHERE m.id=?";

        return memberDao.getDataMap(sql, member_id);
    }

    @Override
    @Transactional
    public void saveMembers(List<Member> members) throws Exception {
        for(Member member:members){
            if(haveDept(member)){
                add(member);
            }
        }
        //memberRepository.save(members);
    }
    public boolean haveDept(Member member){
        if(member.getDeptId()>0){
            Dept  dept = deptDao.findById(member.getDeptId());
            if(dept != null){
                return true;
            }
            return false;
        }
        return true;
    }

    @Override
    public Member updateStatus(Integer memberId, Integer status) {
        Member member = memberRepository.findOne(memberId);
        member.setEmployStatus(status);
        member.setWristBandsNumber(null);
        member.setIcCard(null);
        if(status > 3)
            member.setMobile(member.getMobile()+(System.currentTimeMillis()+"").substring(4,12));
        member = memberRepository.save(member);
        //离场
        if(member.getFaceUserId()!=null && member.getFaceUserId()>0)
            this.pushToHaqiFaceRecognition(member);
        return member;
    }

    @Override
    public void bindWristBrindsNumber(String wristBandsNumber, Integer memberId) throws Exception {
        Member member = this.getMemberById(memberId);
        if(!StringUtil.isEmpty(member.getWristBandsNumber())){
        	if(!member.getWristBandsNumber().equals(wristBandsNumber)){
        		throw new Exception("该会员已经绑定了手环");
        	}else{
        		return ;
        	}            
        }
        if(3 == member.getEmployStatus()){
            throw new Exception("绑定失败，该会员已离场");
        }
        String errorMsg = this.judgeWristBindsNumberAndMeneber(wristBandsNumber);
        if(!StringUtil.isEmpty(errorMsg)){
            throw new Exception(errorMsg);
        }
        member.setWristBandsNumber(wristBandsNumber);
        member.setBindTime(new Date());
        memberRepository.save(member);
    }

    private Member getMemberById(Integer memberId) throws Exception {
        Member member = memberRepository.findOne(memberId);
        if(member == null){
            throw new Exception("会员不存在");
        }
        return member;
    }

    private String judgeWristBindsNumberAndMeneber(String wristBandsNumber) throws Exception {
        //1.wristBandsNumber 没被占用
        List<Member> members = memberRepository.findByWristBandsNumber(wristBandsNumber);
        if(!CollectionUtils.isEmpty(members)){
            throw new Exception("手环卡号已被占用");
        }
        return null;
    }

    @Override
    public void cancelBind(Integer memberId)  throws Exception{
        Member member = this.getMemberById(memberId);
        member.setWristBandsNumber(null);
        member.setIcCard(null);
        member.setBindTime(null);
        memberRepository.save(member);
    }

    @Override
    public void updateHead(String headUrl, Member member) throws Exception {
        Member dbMember = getMemberById(member.getId());
        member.setFaceUrl(headUrl);
        boolean needPush = this.judgeNeedPush(member,dbMember);
        dbMember.setFaceUrl(headUrl);
        memberRepository.save(dbMember);
        if(needPush){
           // this.pushToHaqiFaceRecognition(dbMember);
            String msg = this.pushToHaqiFaceRecognition(dbMember);
            if(msg != null){
                throw new Exception(msg);
            }
        }
    }

    
    /**
	 * 更新Member 状态
	 */
    @Override
	public void updateMemberStatus(){
    	memberDao.updateMemberStatus();
    }

    @Override
    public boolean updateClientMemberStatus(Integer clientId,Integer employStatus){
	    //1.获取会员
        if((clientId == null || clientId<1) || (employStatus == null || employStatus<Constant.IN_SPACE && employStatus>Constant.DELETE_MEMEBER)){
            return false;
        }
        Kv kv = Kv.of("client_id", clientId);
        List<Member> members = findMemberList(kv);
        if(CollectionUtils.isEmpty(members)){
            log.info("updateClientMember empty member:"+clientId);
            return false;
        }
        //2.批量更改
        for(Member m:members){
            m.setEmployStatus(employStatus);
        }
        try{
            memberRepository.save(members);
            return true;
        }catch(Exception e){
            e.printStackTrace();
        }

        return false;
    }
}
